|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
namespace Roslyn.Utilities;
internal sealed class CancellableLazy<T>
{
private NonReentrantLock? _gate;
private Func<CancellationToken, T>? _valueFactory;
private T? _value;
public CancellableLazy(Func<CancellationToken, T> valueFactory)
{
_gate = new NonReentrantLock();
_valueFactory = valueFactory;
}
public CancellableLazy(T value)
=> _value = value;
public bool HasValue
{
get
{
return this.TryGetValue(out _);
}
}
public bool TryGetValue([MaybeNullWhen(false)] out T value)
{
if (_valueFactory == null)
{
value = _value!;
return true;
}
else
{
value = default;
return false;
}
}
public T GetValue(CancellationToken cancellationToken = default)
{
var gate = _gate;
if (gate != null)
{
using (gate.DisposableWait(cancellationToken))
{
if (_valueFactory != null)
{
_value = _valueFactory(cancellationToken);
Interlocked.Exchange<Func<CancellationToken, T>?>(ref _valueFactory, null);
}
Interlocked.Exchange(ref _gate, null);
}
}
return _value!;
}
}
|